package com.only.common.util.ssh;

import cn.hutool.core.util.StrUtil;
import lombok.Data;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 记录已经使用的端
 * @author only
 * @date 2023/12/28
 * @description
 */
@Data
public class UsedPortsResult {
    /**
     * 是否成功
     */
    private boolean successful;

    /**
     * 错误消息
     */
    private String errorMessage;

    /**
     * 已使用的端口
     */
    private List<Integer> usedPorts = new ArrayList<>();

    public UsedPortsResult(String errorMessage) {
        this.errorMessage = errorMessage;
        this.successful = false;
    }

    public UsedPortsResult(List<Integer> usedPorts) {
        this.usedPorts = usedPorts;
        this.successful = true;
    }

    /**
     * 随机获取一个没有使用的端口，如果无法分配端口，返回 -1
     * @return
     */
    public Integer randomValidPort() {
        int range = 65535 - 1025;
        for (int i = 0; i < 2000; i++) {
            Integer port = 1025 + (int) (Math.random() * range);
            if (!usedPorts.contains(port)) {
                usedPorts.add(port); // 本次分配的端口，也被看作已经使用了
                return port;
            }
        }
        return -1;
    }

    public static UsedPortsResult parsingPorts(String content) {
        List<String> lines = Arrays.asList(content.split("\n"));
        List<Integer> ports = lines.stream()
            .map(UsedPortsResult::parsingPort)
            .filter(Optional::isPresent)
            .map(Optional::get)
            .collect(Collectors.toList());
        return new UsedPortsResult(ports);
    }

    private static Optional<Integer> parsingPort(String line) {
        String content = line.trim();
        if (StrUtil.isBlank(content)) {
            return Optional.empty();
        } else {
            int idx = content.lastIndexOf(":");
            if (idx == -1) {
                return Optional.empty();
            } else {
                try {
                    String port = content.substring(idx + 1);
                    return Optional.of(Integer.valueOf(port));
                } catch (Exception ex) {
                    return Optional.empty();
                }
            }
        }
    }
}
